package com.njupt.simulation.utils;

import java.util.Arrays;

public class CalculateCDF {
    /**
     * 计算CDF
     *
     * @param totalnum 总数据量或者总时刻或者总的调用算法次数
     * @return
     */
    public static double[] calculateCDF(int totalnum) {
        double[] cdf = new double[totalnum];
        for (int i = 0; i < totalnum; i++) {
            cdf[i] = (i + 0.1) / totalnum;
        }
        return cdf;
    }


    /**
     * 计算并打印CDF在指定区间内的值
     *
     * @param data 数据点数组
     */
    public static void calculateAndPrintCDF(double[] data) {

        double[] shuju = new double[0];
        double max = data[0];
        double min = data[0];

        // 遍历数组，从第二个元素开始比较
        for (int i = 1; i < data.length; i++) {
            if (data[i] > max) {
                max = data[i];
            }
            if (data[i] < min) {
                min = data[i];
            }
        }

        // 对数据进行排序
        Arrays.sort(data);

        // 总数据点数
        int totalDataPoints = data.length;

        // 输出表头
        System.out.println("x\tCDF(x)");

        // 遍历区间 [start, end]，按步长计算CDF(x)
        for (double x = min; x <= max; x += 0.1) {
            // 计算小于或等于x的数据点个数
            int count = countLessThanOrEqualTo(data, x);

            // 计算CDF(x)
            double cdf = (double) count / totalDataPoints;

            // 输出结果
            System.out.printf("%.1f\t%.4f\n", x, cdf);
        }
    }

    /**
     * 统计小于或等于给定值x的数据点个数
     *
     * @param data 数据点数组（已排序）
     * @param x    目标值
     * @return 小于或等于x的数据点个数
     */
    public static int countLessThanOrEqualTo(double[] data, double x) {
        // 使用二分查找确定x的位置
        int index = Arrays.binarySearch(data, x);

        // 如果x不在数组中，返回插入点
        if (index < 0) {
            index = -(index + 1) - 1; // 找到小于x的最大值的索引
        } else {
            // 如果x在数组中，找到最后一个等于x的位置
            while (index < data.length - 1 && data[index + 1] == x) {
                index++;
            }
        }

        // 返回小于或等于x的数据点个数
        return index + 1;
    }



    public static void main(String[] args) {
        // 示例数据（无序，范围可以是任意值）
        double[] data = {3, -5, 7, 8, -10, 12, 13, 15, 16, 18, -25, 30, -30, 100, -100};

        // 计算CDF在区间 [-30, 30] 内的值
        calculateAndPrintCDF(data);
    }
}
